<?php

/**
 * @author yeran
 * @createTime 2018-10-30
 *
 * @desc 撤单处理类
 */

namespace Payment\Client;


use Payment\CancelContext;
use Payment\Common\PayException;
use Payment\Config;

class Cancel
{
    private static $supportChannel = [
        Config::ALI_CHANNEL_APP,// 支付宝 APP 支付
        Config::ALI_CHANNEL_WAP, // 支付宝手机网页支付
        Config::ALI_CHANNEL_WEB, // 支付宝电脑网站支付
        Config::ALI_CHANNEL_QR, // 支付宝当面付-扫码支付
        Config::ALI_CHANNEL_BAR,// 支付宝当面付-条码支付

        Config::WX_CHANNEL_APP,// 微信 APP 支付
        Config::WX_CHANNEL_PUB,// 微信公众号支付
        Config::WX_CHANNEL_QR,// 微信公众号扫码支付
        Config::WX_CHANNEL_BAR,// 微信刷卡支付
        Config::WX_CHANNEL_WAP,// 微信 WAP 支付（此渠道仅针对特定客户开放）
        Config::WX_CHANNEL_LITE,// 微信小程序支付

        Config::CMB_CHANNEL_APP,// 招行一网通

        Config::APPLE_PAY,// Apple Pay

        Config::TL_CHANNEL_LITE,//通联支付

        Config::MI_CHANNEL_LITE, //米付

        Config::SW_CHARGE, //扫呗支付退款
        Config::SW_T_CHARGE, //扫呗支付(3.0)撤销(退款)

        Config::FU_CHARGE, //富友
		Config::LTF_CHARGE,

		Config::YS_CHARGE,//易生支付
    ];

    /**
     * 异步通知类
     * @var CancelContext
     */
    protected static $instance;

    protected static function getInstance($channel, $config)
    {
        if (is_null(self::$instance)) {
            static::$instance = new CancelContext();

            try {
                static::$instance->initCancelHandler($channel, $config);
            } catch (PayException $e) {
                throw $e;
            }
        }

        return static::$instance;
    }

    /**
     * @param string $channel
     * @param array $config
     * @param array $metadata
     *
     * @return mixed
     * @throws PayException
     */
    public static function run($channel, $config, $metadata)
    {
        if (!in_array($channel, self::$supportChannel)) {
            throw new PayException('sdk当前不支持该支付渠道，当前仅支持：' . implode(',', self::$supportChannel));
        }

        try {
            $instance = self::getInstance($channel, $config);

            $ret = $instance->cancel($metadata);
        } catch (PayException $e) {
            throw $e;
        }

        return $ret;
    }
}
